﻿using Engine;
using Game;
using GameEntitySystem;
using SAGhoul.Blocks;
using System.Collections.Generic;
using System.Linq;
using TemplatesDatabase;

namespace SAGhoul
{
	/// <summary>
	/// 灵魂护甲组件 - 提供特殊护甲套装效果
	/// 当穿戴完整套装时提供强力保护和特殊能力
	/// </summary>
	public class ComponentClothingMass : Component, IUpdateable
	{
		enum ArmorState
		{// 状态枚举
			Inactive,// 未激活
			Active,// 激活状态
			Cooldown,// 冷却中
			LowSouls// 灵魂不足
		}
		public const float HealthRestoreAmount = 1f;// 生命恢复量
		public const float ExplosionResilienceBonus = 5;// 爆炸抗性加成
		public const float FireResilienceBonus = 80;// 火焰抗性加成
		public const float AttackResilience = 10;// 攻击抗性系数
		public const float FallResilienceBonus = 7;// 坠落抗性加成
		public const double DeathPreventionCooldown = 20.0;// 生命恢复冷却时间(20秒)
		public const float WetnessResetRate = 15f;// 湿度重置速率
		public const string SoulResidueClassName = "LargeSoulsResidueBlock";// 灵魂残渣类名
		public const int RequiredSoulResidueCountForHeal = 3;// 生命恢复所需灵魂残渣数量
		public const int RequiredSoulResidueCountForCleanse = 1;// 清除状态所需灵魂残渣数量
		public const string RestorationSound = "Audio/Souls_Exp/Souls_Exp0";// 恢复音效
		public const float RecoveryInterval = 2.0f;// 每2秒恢复一次
		public const int AcIndex = 94;
		public const float AcStaminaRegenPerSecond = 0.01f; // 每秒恢复耐力（0到1）

		public static int[] RequiredClothingIndices
		{// 所需护甲索引
			get; set;
		} = [90, 91, 92, 93];
		public UpdateOrder UpdateOrder => UpdateOrder.Default;

		public SubsystemGameInfo m_subsystemGameInfo;// 游戏信息子系统
		public SubsystemAudio m_subsystemAudio;// 音频子系统
		public SubsystemTime m_subsystemTime;// 时间子系统
		public SubsystemPickables m_subsystemPickables;// 可拾取物子系统
		public ComponentCreature m_componentCreature;// 生物组件
		public ComponentClothing m_componentClothing;// 护甲组件
		public ComponentHealth m_componentHealth;// 生命组件
		public ComponentVitalStats m_componentVitalStats;// 生命统计组件

		public float ArmorProtection
		{
			get; set;
		}

		LabelWidget m_soulStatusLabel;// 灵魂状态标签
		ValueBarWidget m_armorBar;

		// 基础属性
		float m_baseExplosionResilience;// 基础爆炸抗性
		float m_baseFireResilience;// 基础火焰抗性
		float m_baseAttackResilience;// 基础攻击抗性
		float m_baseFallResilience;// 基础坠落抗性
		float m_baseHealFactor;// 基础治疗系数

		// 状态变量
		ArmorState m_currentState;// 当前护甲状态
		bool m_hasShownPostRestoreWarning;// 是否已显示恢复后警告
		double m_lastRestoreTime;// 上次恢复时间
		double m_lastCleanseTime;// 上次清除状态时间
		bool m_hasStatusEffect;// 是否有异常状态
		float m_recoveryTimer;
		float activatedMessageCd;

		public override void Load(ValuesDictionary valuesDictionary, IdToEntityMap idToEntityMap)
		{
			base.Load(valuesDictionary, idToEntityMap);
			InitializeComponents(valuesDictionary);
			InitializeBaseAttributes();
			m_currentState = ArmorState.Inactive;
			m_hasShownPostRestoreWarning = false;
			m_lastRestoreTime = double.MinValue;
			m_lastCleanseTime = double.MinValue;
			activatedMessageCd = 3f;
			m_armorBar = new ValueBarWidget()
			{
				LayoutDirection = LayoutDirection.Horizontal,
				HorizontalAlignment = WidgetAlignment.Center,
				BarsCount = 10,
				Spacing = -1,
				BarBlending = false,
				HalfBars = true,
				LitBarColor = new Color(192, 173, 197),
				UnlitBarColor = Color.DarkGray,
				BarSize = new Vector2(16f),
				TextureLinearFilter = true,
				BarSubtexture = ContentManager.Get<Subtexture>("Textures/Atlas/SAG_Armor")
			};
			m_componentClothing.m_componentPlayer.GameWidget.Children.Find<StackPanelWidget>("BottomWidgetsContainer").Children.Insert(1, m_armorBar);
		}
		public override void OnEntityAdded()
		{
			base.OnEntityAdded();
			m_componentHealth?.Injured += OnInjured;
			m_currentState = ArmorState.Inactive;
			m_hasShownPostRestoreWarning = false;
			m_lastRestoreTime = double.MinValue;
			m_lastCleanseTime = double.MinValue;
			ResetToBaseValues();
		}
		public override void OnEntityRemoved()
		{
			base.OnEntityRemoved();
			CleanupEventHandlers();
			RemoveStatusLabel();
			m_componentClothing.m_componentPlayer.GameWidget.Children.Find<StackPanelWidget>("BottomWidgetsContainer").RemoveChildren(m_armorBar);
		}
		public void Update(float dt)
		{
			activatedMessageCd = MathUtils.Max(0, activatedMessageCd - dt);
			var armorCheck = CheckArmorStatus();
			UpdateArmorState(armorCheck);
			UpdateSoulStatus(armorCheck);
			if (armorCheck.HasFullSet && m_componentVitalStats != null)
			{// 保持身体干燥效果
				m_recoveryTimer += dt;
				if (m_recoveryTimer >= RecoveryInterval)
				{
					m_componentVitalStats.Wetness = MathUtils.Max(0f,
						m_componentVitalStats.Wetness - WetnessResetRate * RecoveryInterval);
					m_recoveryTimer = 0f;
				}
			}
			if (m_componentVitalStats != null && IsAcArmorEquipped())
			{//当任意护甲槽装备索引为 AcIndex 的护甲时，持续恢复耐力
				float currentStamina = m_componentVitalStats.Stamina;
				if (currentStamina < 1f)
				{// 平滑按帧恢复：按秒率乘以 dt，且不超过最大（耐力上限为 1.0）
					m_componentVitalStats.Stamina = MathUtils.Min(1f, currentStamina + AcStaminaRegenPerSecond * dt);
				}
			}
			m_armorBar.IsVisible = m_subsystemGameInfo.WorldSettings.GameMode != GameMode.Creative && ArmorProtection > 0f;
			m_armorBar.Value = ArmorProtection;
			// 检查并清除异常状态
			CheckAndCleanseStatusEffects();
		}

		void InitializeComponents(ValuesDictionary valuesDictionary)
		{// 初始化组件
			m_componentCreature = Entity.FindComponent<ComponentCreature>(throwOnError: true);
			m_componentClothing = Entity.FindComponent<ComponentClothing>(throwOnError: true);
			m_componentHealth = Entity.FindComponent<ComponentHealth>(throwOnError: true);
			m_componentVitalStats = Entity.FindComponent<ComponentVitalStats>(throwOnError: true);
			m_subsystemGameInfo = Project.FindSubsystem<SubsystemGameInfo>(throwOnError: true);
			m_subsystemAudio = Project.FindSubsystem<SubsystemAudio>(throwOnError: true);
			m_subsystemTime = Project.FindSubsystem<SubsystemTime>(throwOnError: true);
			m_subsystemPickables = Project.FindSubsystem<SubsystemPickables>(throwOnError: true);
		}
		void InitializeBaseAttributes()
		{// 初始化基础属性
			ValuesDictionary entityValues = DatabaseManager.FindEntityValuesDictionary(
				Entity.ValuesDictionary.DatabaseObject.Name, throwIfNotFound: true);
			ValuesDictionary healthValues = entityValues.GetValue<ValuesDictionary>("Health");
			m_baseExplosionResilience = healthValues.GetValue<float>("ExplosionResilience");
			m_baseFireResilience = healthValues.GetValue<float>("FireResilience");
			m_baseAttackResilience = healthValues.GetValue<float>("AttackResilience");
			m_baseFallResilience = healthValues.GetValue<float>("FallResilience");
			m_baseHealFactor = healthValues.GetValue<float>("HealFactor");
		}
		void CleanupEventHandlers()
		{// 清理事件处理器
			m_componentHealth?.Injured -= OnInjured;
		}
		void RemoveStatusLabel()
		{// 移除状态标签
			var componentPlayer = m_componentCreature?.Entity.FindComponent<ComponentPlayer>();
			if (componentPlayer != null && m_soulStatusLabel != null)
			{
				componentPlayer.ComponentGui.ControlsContainerWidget.Children.Remove(m_soulStatusLabel);
			}
		}
		void OnInjured(Injury injury)
		{// 受伤事件处理
			if (m_currentState != ArmorState.Active)
				return;
			bool isFatalDamage = injury.Amount >= m_componentHealth.Health;
			if (!isFatalDamage)
				return;
			// 检查冷却是否完成
			bool isCooldownComplete = (m_subsystemTime.GameTime - m_lastRestoreTime) >= DeathPreventionCooldown;

			var armorCheck = CheckArmorStatus();
			if (armorCheck.HasFullSet && HasEnoughSoulResidue(RequiredSoulResidueCountForHeal) && isCooldownComplete)
			{
				HandleFatalDamageProtection(injury, armorCheck);
			}
			else if (!m_hasShownPostRestoreWarning)
			{
				ShowSoulStatus(!HasEnoughSoulResidue(RequiredSoulResidueCountForHeal) || !isCooldownComplete);
				m_hasShownPostRestoreWarning = true;
			}
		}


		bool HasEnoughSoulResidue(int requiredCount)
		{// 检查是否有足够灵魂残渣
			var componentPlayer = m_componentCreature.Entity.FindComponent<ComponentPlayer>();
			if (componentPlayer == null)
				return false;
			var inventory = componentPlayer.ComponentMiner.Inventory;
			int count = 0;
			for (int i = 0; i < inventory.SlotsCount; i++)
			{
				int slotValue = inventory.GetSlotValue(i);
				if (slotValue != 0)
				{
					Block block = BlocksManager.Blocks[Terrain.ExtractContents(slotValue)];
					if (block is LargeSoulsResidueBlock)
					{
						count += inventory.GetSlotCount(i);
						if (count >= requiredCount)
							return true;
					}
				}
			}
			return count >= requiredCount;
		}
		void ConsumeSoulResidue(int amount)
		{// 消耗灵魂残渣
			var componentPlayer = m_componentCreature.Entity.FindComponent<ComponentPlayer>();
			if (componentPlayer == null)
				return;
			var inventory = componentPlayer.ComponentMiner.Inventory;
			int remainingToConsume = amount;
			for (int i = 0; i < inventory.SlotsCount && remainingToConsume > 0; i++)
			{
				int slotValue = inventory.GetSlotValue(i);
				if (slotValue != 0)
				{
					Block block = BlocksManager.Blocks[Terrain.ExtractContents(slotValue)];
					if (block is LargeSoulsResidueBlock)
					{
						int slotCount = inventory.GetSlotCount(i);
						int consumeAmount = MathUtils.Min(slotCount, remainingToConsume);
						inventory.RemoveSlotItems(i, consumeAmount);
						remainingToConsume -= consumeAmount;
					}
				}
			}
		}
		void HandleFatalDamageProtection(Injury injury, (bool HasFullSet, bool HasSufficientSouls) armorCheck)
		{// 处理致命伤害保护
			injury.Amount = 0f;
			ConsumeSoulResidue(RequiredSoulResidueCountForHeal);
			TriggerFullRestoration();
			m_lastRestoreTime = m_subsystemTime.GameTime; // 记录恢复时间
			m_currentState = ArmorState.Cooldown;
			m_subsystemTime.QueueGameTimeDelayedExecution(
				m_subsystemTime.GameTime + DeathPreventionCooldown,
				() =>
				{
					bool hasSouls = HasEnoughSoulResidue(RequiredSoulResidueCountForHeal);
					m_currentState = hasSouls ? ArmorState.Active : ArmorState.LowSouls;
					ShowSoulStatus(!hasSouls);
				});
		}
		void CheckAndCleanseStatusEffects()
		{// 检查并清除异常状态
			if (m_currentState != ArmorState.Active)
				return;
			// 检查是否有异常状态
			bool hasFlu = HasFlu();
			bool hasSickness = HasSickness();
			m_hasStatusEffect = hasFlu || hasSickness;
			// 如果有异常状态且冷却完成且有足够灵魂残渣
			if (m_hasStatusEffect &&
				(m_subsystemTime.GameTime - m_lastCleanseTime) >= 5.0 &&
				HasEnoughSoulResidue(RequiredSoulResidueCountForCleanse))
			{
				ConsumeSoulResidue(RequiredSoulResidueCountForCleanse);
				ClearAllSicknessEffects();
				m_lastCleanseTime = m_subsystemTime.GameTime;
				// 显示清除状态通知
				var componentPlayer = m_componentCreature.Entity.FindComponent<ComponentPlayer>();
				componentPlayer?.ComponentGui.DisplaySmallMessage(
					this.Lang("StatusEffectClear"),
					Color.LightBlue,
					blinking: true,
					playNotificationSound: true);
			}
		}
		bool HasFlu()
		{// 检查是否有流感
			var componentFlu = m_componentCreature.Entity.FindComponent<ComponentFlu>();
			return componentFlu != null &&
				  (componentFlu.m_fluDuration > 0f ||
				   componentFlu.m_coughDuration > 0f ||
				   componentFlu.m_sneezeDuration > 0f);
		}
		bool HasSickness()
		{// 检查是否有疾病
			var componentSickness = m_componentCreature.Entity.FindComponent<ComponentSickness>();
			return componentSickness != null && componentSickness.m_sicknessDuration > 0f;
		}
		void UpdateArmorState((bool HasFullSet, bool HasSufficientSouls) armorCheck)
		{// 更新护甲状态
			if (armorCheck.HasFullSet && m_currentState != ArmorState.Active && m_currentState != ArmorState.Cooldown)
			{
				ActivateArmorSet();
			}
			else if (!armorCheck.HasFullSet && m_currentState != ArmorState.Inactive)
			{
				DeactivateArmorSet();
			}
		}
		void ActivateArmorSet()
		{// 激活护甲套装效果
			ApplyFullSetEffects();
			ShowSetActivatedMessage();
			m_currentState = ArmorState.Active;
		}
		void DeactivateArmorSet()
		{// 禁用护甲套装效果
			ResetToBaseValues();
			ShowSoulStatus(false);
			m_currentState = ArmorState.Inactive;
		}
		void UpdateSoulStatus((bool HasFullSet, bool HasSufficientSouls) armorCheck)
		{// 更新灵魂状态显示
			if (m_currentState == ArmorState.Active)
			{
				bool isCooldownComplete = (m_subsystemTime.GameTime - m_lastRestoreTime) >= DeathPreventionCooldown;
				bool showWarning = !HasEnoughSoulResidue(RequiredSoulResidueCountForHeal) || !isCooldownComplete;
				ShowSoulStatus(showWarning);
				if (showWarning && !m_hasShownPostRestoreWarning)
				{
					m_hasShownPostRestoreWarning = true;
					m_currentState = ArmorState.LowSouls;
				}
			}
		}
		void ShowSoulStatus(bool showWarning)
		{// 显示灵魂状态
			var componentPlayer = m_componentCreature.Entity.FindComponent<ComponentPlayer>();
			var (HasFullSet, _) = CheckArmorStatus();
			if (componentPlayer == null)
				return;
			if (!HasFullSet)
			{
				m_soulStatusLabel?.IsVisible = false;
				return;
			}
			InitializeStatusLabelIfNeeded(componentPlayer);
			UpdateStatusLabelAppearance(showWarning);
		}
		void InitializeStatusLabelIfNeeded(ComponentPlayer componentPlayer)
		{// 初始化状态标签(如果需要)
			if (m_soulStatusLabel == null)
			{
				m_soulStatusLabel = new LabelWidget
				{
					FontScale = 0.75f,
					HorizontalAlignment = WidgetAlignment.Near,
					VerticalAlignment = WidgetAlignment.Center,
					Margin = new Vector2(5f, 25f)
				};
				componentPlayer.ComponentGui.ControlsContainerWidget.Children.Add(m_soulStatusLabel);
			}
		}
		void UpdateStatusLabelAppearance(bool showWarning)
		{// 更新状态标签外观
			bool isCooldownComplete = (m_subsystemTime.GameTime - m_lastRestoreTime) >= DeathPreventionCooldown;
			bool hasStatusEffect = m_hasStatusEffect;
			if (isCooldownComplete && !showWarning)
			{// 冷却完成且灵魂充足时显示
				string statusText = " " + this.Lang("StatusUp") + "\n" + this.Lang("FullSoul");
				if (hasStatusEffect)
					statusText += "\n(" + this.Lang("AbnormalDetected") + ")";
				m_soulStatusLabel.Text = statusText;
				m_soulStatusLabel.Color = hasStatusEffect ? Color.Orange : Color.LightBlue;
			}
			else
			{// 其他所有情况（冷却中、灵魂不足或两者同时发生）均显示灵魂不足
				string message = " " + this.Lang("StatusUp") + "\n" + this.Lang("LackSoul");
				if (!isCooldownComplete)
				{
					double remainingTime = DeathPreventionCooldown - (m_subsystemTime.GameTime - m_lastRestoreTime);
					message += $"\n{this.Lang("Cooling")}: {remainingTime:0.0}s";
				}
				if (hasStatusEffect)
				{
					message += "\n(" + this.Lang("AbnormalDetected") + ")";
				}
				m_soulStatusLabel.Text = message;
				m_soulStatusLabel.Color = !isCooldownComplete ? Color.Orange : Color.DarkBlue;
			}
			m_soulStatusLabel.IsVisible = true;
		}
		void ApplyFullSetEffects()
		{// 应用全套效果
			m_componentHealth.ExplosionResilience = m_baseExplosionResilience + ExplosionResilienceBonus;
			m_componentHealth.FireResilience = m_baseFireResilience + FireResilienceBonus;
			m_componentHealth.AttackResilience = m_baseAttackResilience + AttackResilience;
			m_componentHealth.FallResilience = m_baseFallResilience + FallResilienceBonus;
		}
		void ResetToBaseValues()
		{// 重置为基础值
			m_componentHealth.ExplosionResilience = m_baseExplosionResilience;
			m_componentHealth.FireResilience = m_baseFireResilience;
			m_componentHealth.AttackResilience = m_baseAttackResilience;
			m_componentHealth.FallResilience = m_baseFallResilience;
			m_componentHealth.HealFactor = m_baseHealFactor;
		}
		void TriggerFullRestoration()
		{// 触发完全恢复
			PlayRestorationSound();
			RestoreHealth();
			ClearAllSicknessEffects();
			ShowRestorationNotification();
		}
		void PlayRestorationSound()
		{// 播放恢复音效
			m_subsystemAudio.PlaySound(
				RestorationSound,
				2f,
				0f,
				m_componentCreature.ComponentBody.Position,
				4f,
				autoDelay: true);
		}
		void RestoreHealth()
		{// 恢复生命值
			m_componentHealth.Health = HealthRestoreAmount;
		}
		void ShowRestorationNotification()
		{// 显示恢复通知
			var componentPlayer = m_componentCreature.Entity.FindComponent<ComponentPlayer>();
			componentPlayer?.ComponentGui.DisplaySmallMessage(
				string.Format(this.Lang("Restoration"), RequiredSoulResidueCountForHeal, DeathPreventionCooldown),
				Color.LightYellow,
				blinking: true,
				playNotificationSound: true);
		}
		void ClearAllSicknessEffects()
		{// 清除所有疾病效果
			ClearFluEffects();
			ClearSicknessEffects();
		}
		void ClearFluEffects()
		{// 清除流感效果
			var componentFlu = m_componentCreature.Entity.FindComponent<ComponentFlu>();
			if (componentFlu != null)
			{
				componentFlu.m_fluDuration = 0f;
				componentFlu.m_fluOnset = 0f;
				componentFlu.m_coughDuration = 0f;
				componentFlu.m_sneezeDuration = 0f;
				componentFlu.m_blackoutDuration = 0f;
				componentFlu.m_blackoutFactor = 0f;
			}
		}
		void ClearSicknessEffects()
		{// 清除疾病效果
			var componentSickness = m_componentCreature.Entity.FindComponent<ComponentSickness>();
			if (componentSickness != null)
			{
				componentSickness.m_sicknessDuration = 0f;
				componentSickness.m_greenoutDuration = 0f;
				componentSickness.m_greenoutFactor = 0f;
				componentSickness.m_pukeParticleSystem = null;
			}
		}
		void ShowSetActivatedMessage()
		{// 显示套装激活消息
			if (activatedMessageCd > 0f)
				return;
			var componentPlayer = m_componentCreature.Entity.FindComponent<ComponentPlayer>();
			componentPlayer?.ComponentGui.DisplaySmallMessage(
				string.Format(this.Lang("FullSet"), RequiredSoulResidueCountForHeal, SAGhoulsManager.GetBlockDisplayName(typeof(LargeSoulsResidueBlock)), DeathPreventionCooldown, RequiredSoulResidueCountForCleanse, SAGhoulsManager.GetBlockDisplayName(typeof(LargeSoulsResidueBlock))),
				Color.Purple,
				blinking: true,
				playNotificationSound: true);
			activatedMessageCd = 5f;
		}
		(bool HasFullSet, bool HasSufficientSouls) CheckArmorStatus()
		{// 检查护甲状态
			var equippedIndices = new HashSet<int>();
			bool hasSufficientSouls = HasEnoughSoulResidue(RequiredSoulResidueCountForHeal);

			for (int slot = 0; slot < 4; slot++)
			{
				foreach (int clothe in m_componentClothing.GetClothes((ClothingSlot)slot))
				{
					Block block = BlocksManager.Blocks[Terrain.ExtractContents(clothe)];
					ClothingData clothingData = block.GetClothingData(clothe);

					if (clothingData == null || !RequiredClothingIndices.Contains(clothingData.Index))
						continue;

					equippedIndices.Add(clothingData.Index);
				}
			}
			bool hasFullSet = RequiredClothingIndices.All(index => equippedIndices.Contains(index));
			return (hasFullSet, hasSufficientSouls);
		}

		
		bool IsAcArmorEquipped()
		{//检查是否装备了索引为 AcIndex 的护甲（任意槽）
			if (m_componentClothing == null)
				return false;
			for (int slot = 0; slot < 4; slot++)
			{
				foreach (int clothe in m_componentClothing.GetClothes((ClothingSlot)slot))
				{
					Block block = BlocksManager.Blocks[Terrain.ExtractContents(clothe)];
					ClothingData clothingData = block.GetClothingData(clothe);
					if (clothingData != null && clothingData.Index == AcIndex)
						return true;
				}
			}
			return false;
		}

	}
}